<?php
class pgsqldriver extends abstractdbdriver
{

	public function __construct($dbinfo)
	{
		if (!empty($dbinfo['dbname']))
		{
			if ($dbinfo['persistent'])
			$this->connection = pg_pconnect("host={$dbinfo['dbname']} port=5432 dbname={$dbinfo['dbname']} user={$dbinfo['$dbuser']} password={$dbinfo['dbpwd']}");
			else
			$this->connection = pg_connect("host={$dbinfo['dbname']} port=5432 dbname={$dbinfo['dbname']} user={$dbinfo['$dbuser']} password={$dbinfo['dbpwd']}");
		}
		else
		throw new Exception("You must supply username, password, hostname and database name for connecting to postgresql");
	}

	public function execute($sql)
	{
		$sql = $this->prepQuery($sql);
		$parts = split(" ",trim($sql));
		$type = strtolower($parts[0]);
		$hash = md5($sql);
		$this->lasthash = $hash;

		if ("select"==$type)
		{
			if (isset($this->results[$hash]))
			{
				if (is_resource($this->results[$hash])){
					pg_result_seek($this->results[$hash],0);
					return $this->results[$hash];
				}
			}
		}
		else if("update"==$type || "delete"==$type)
		{
			$this->results = array(); //clear the result cache
		}
		$this->results[$hash] = pg_query($this->connection,$sql);
		if("insert"==$type) return $this->insertId();
		return true;
	}

	public function count()
	{
		//print_r($this);
		$lastresult = $this->results[$this->lasthash];
		//print_r($this->results);
		$count = pg_num_rows($lastresult);
		if (!$count) $count = 0;
		return $count;
	}


	private  function prepQuery($sql)
	{
		// "DELETE FROM TABLE" returns 0 affected rows This hack modifies
		// the query so that it returns the number of affected rows
		if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql))
		{
			$sql = preg_replace("/^\s*DELETE\s+FROM\s+(\S+)\s*$/", "DELETE FROM \\1 WHERE 1=1", $sql);
		}


		return $sql;
	}

	public function escape($sql)
	{
		if (function_exists('pg_escape_string'))
		{
			return pg_escape_string( $sql);
		}
		else
		{
			return addslashes($sql);
		}
	}


	public function affectedRows()
	{
		return @pg_affected_rows($this->connection);
	}

	public function insertId($table=null, $column=null)
	{
		$_temp = $this->lasthash;
		$lastresult = $this->results[$this->lasthash];
		$this->execute("SELECT version() AS ver");

		$row = $this->getRow();
		$v = $row['server'];

		$table	= func_num_args() > 0 ? func_get_arg(0) : null;
		$column	= func_num_args() > 1 ? func_get_arg(1) : null;

		if ($table == null && $v >= '8.1')
		{
			$sql='SELECT LASTVAL() as ins_id';
		}
		elseif ($table != null && $column != null && $v >= '8.0')
		{
			$sql = sprintf("SELECT pg_get_serial_sequence('%s','%s') as seq", $table, $column);
			$this->execte($sql);
			$row = $this->getRow();
			$sql = sprintf("SELECT CURRVAL('%s') as ins_id", $row['seq']);
		}
		elseif ($table != null)
		{
			// seq_name passed in table parameter
			$sql = sprintf("SELECT CURRVAL('%s') as ins_id", $table);
		}
		else
		{
			return pg_last_oid($lastresult);
		}
		$this->execute($sql);
		$row = $this->getRow();
		$this->lasthash = $_temp;
		return $row['ins_id'];
	}


	public function transBegin()
	{
		return @pg_exec($this->connection, "BEGIN");
		return TRUE;
	}

	public function transCommit()
	{
		return @pg_exec($this->connection, "COMMIT");
		return TRUE;
	}


	public function transRollback()
	{
		return @pg_exec($this->connection, "ROLLBACK");
		return TRUE;
	}



	public function getRow($fetchmode = FETCH_ASSOC)
	{

		$lastresult = $this->results[$this->lasthash];
		if (FETCH_ASSOC == $fetchmode)
		$row = pg_fetch_assoc($lastresult);
		elseif (FETCH_ROW == $fetchmode)
		$row = pg_fetch_row($lastresult);
		elseif (FETCH_OBJECT == $fetchmode)
		$row = pg_fetch_object($lastresult);
		else
		$row = pg_fetch_array($lastresult,PGSQL_BOTH);
		return $row;
	}

	public function getRowAt($offset=null,$fetchmode = FETCH_ASSOC)
	{
		$lastresult = $this->results[$this->lasthash];
		if (!empty($offset))
		{
			pg_result_seek($lastresult, $offset);
		}
		return $this->getRow($fetchmode);
	}

	public function rewind()
	{
		$lastresult = $this->results[$this->lasthash];
		pg_result_seek($lastresult, 0);
	}

	public function getRows($start, $count, $fetchmode = FETCH_ASSOC)
	{
		$lastresult = $this->results[$this->lasthash];
		$rows = array();
		for ($i=$start; $i<=($start+$count); $i++)
		{
			$rows[] = $this->getRowAt($i,$fetchmode);
		}
		return $rows;
	}

	function __destruct(){
		foreach ($this->results as $result)
		{
			@pg_free_result($result);
		}
	}


	function getFields($table)
	{
		$this->execute("SELECT column_name FROM information_schema.columns WHERE table_name = {$table}");
		$fields = array();
		while ($row = $this->getRow())
		{
			$fields[] = $row['column_name'];
		}
		return $fields;
	}


}
?>